/*
 * $Id: thr.h,v 1.6 2006-03-29 11:47:46 bacon Exp $
 */

#ifndef _XP_BAS_THR_H_
#define _XP_BAS_THR_H_

#include <xp/types.h>
#include <xp/macros.h>
#include <xp/bas/stdarg.h>
#include <xp/bas/sysapi.h>
#include <xp/bas/time.h>

#if defined(_WIN32)
	#include <process.h>
#elif defined(__BEOS__)
	#include <be/kernel/OS.h>
#else
	#if defined(AIX) && defined(__GNUC__)
		typedef int crid_t;
		typedef unsigned int class_id_t;
	#endif
	#include <pthread.h>
#endif

#if defined(_WIN32)
	#define XP_THRHND_INVALID INVALID_HANDLE_VALUE
	typedef HANDLE xp_thrhnd_t;
#elif defined(__BEOS__)
	#define XP_THRHND_INVALID (-1)
	typedef thread_id xp_thrhnd_t;
#else
	#define XP_THRHND_INVALID 0
	typedef pthread_t xp_thrhnd_t;
#endif

/* GROUP: Types */

/*
 * TYPE: xp_thr_t
 *   Defines a thread object
 *
 * DESCRIPTION:
 *   <xp_thr_t> is a structure to represent a thread object. The pointer
 *   to a <xp_thr_t> object is needed for all thread functions.
 */
typedef struct xp_thr_t xp_thr_t;

/* 
 * TYPE: xp_thr_routine_t
 *   Defines a thread routine
 * 
 * DESCRIPTION:
 *   <xp_thr_routine_t> defines the prototype of a thread routine 
 *   that can be passed to <xp_thr_open> and <xp_thr_start>. 
 *   When it is executed, the pointer to the calling thread object is 
 *   passed as its first argument. A thread routine should conform to 
 *   the following prototype.
 *   - int thread_routine (xp_thr_t*);
 */
typedef	int (*xp_thr_routine_t) (xp_thr_t*);

struct xp_thr_t
{
	xp_bool_t __dynamic;
	xp_thr_routine_t __main_routine;
	xp_thr_routine_t __temp_routine;
	xp_bool_t __joinable;

	xp_thrhnd_t __handle;
	int __state;
	int __return_code;
	void* __user_data;
};

enum 
{
	XP_THR_INCUBATING,
	XP_THR_RUNNING,
	XP_THR_TERMINATED,
	XP_THR_ABORTED
};

#define XP_THR_DETACHED    (1 << 0)
#define XP_THR_NEW_ROUTINE (1 << 1)

#ifdef __cplusplus
extern "C" {
#endif

/* GROUP: Basic */

/* 
 * FUNCTION: xp_thr_open
 *   Instantiates a thread object
 * 
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *   routine - [in] main thread routine 
 *   user_data - [in] extra user data 
 *
 * RETURNS:
 *   Pointer to the thread object on success. XP_NULL on failure
 * 
 * DESCRIPTION:
 *   *thr* can be either a pointer to a variable of the xp_thr_t type or
 *   XP_NULL. <xp_thr_open> allocates required memory if it is XP_NULL.
 *   All individual fields are initialized properly. *routine* is executed when
 *   <xp_thr_start> is called. <xp_thr_getuserdata> returns *user_data*.
 *
 * SEE ALSO:
 *   <xp_thr_close> <xp_thr_start> <xp_thr_getuserdata>
 */
xp_thr_t* xp_thr_open (
	xp_thr_t* thr, xp_thr_routine_t routine, void* user_data);

/* 
 * FUNCTION: xp_thr_close
 *   Destroys a thread object
 *
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *
 * DESCRIPTION:
 *   <xp_thr_close> destroyes a thread object, freeing the resources it 
 *   holds. Make sure that the thread routine has been terminated properly
 *   before <xp_thr_close> is called.
 * 
 * SEE ALSO:
 *   <xp_thr_open>
 */
void xp_thr_close (xp_thr_t* thr);

/* 
 * FUNCTION: xp_thr_start
 *   Executes a thread routine in a new thread of control
 *
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *   flags - [in] 0 or bitwise-or of XP_THR_NEW_ROUTINE and XP_THR_DETACHED 
 *   ... - [in] a temporary thread routine. optional
 *
 * RETURNS:
 *   0 on success, -1 on failure
 *
 * DESCRIPTION:
 *   <xp_thr_start> executes a thread routine set with <xp_thr_open>.
 *   A new temporary thread routine can be passed as the third argument to 
 *   override the main thread routine for a single invocation when 
 *   XP_THR_NEW_ROUTINE is set in *flags*.
 *
 *   XP_THR_DETACHED, when set in *flags*, puts the thread in a detached 
 *   state. Otherwise, the thread is joinable. 
 * 
 * SEE ALSO:
 *   <xp_thr_stop>
 */
int xp_thr_start (xp_thr_t* thr, int flags, ...);

/* 
 * FUNCTION: xp_thr_stop
 *   Aborts a thread
 *
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *
 * RETURNS:
 *   0 on success, -1 on failure
 *
 * DESCRIPTION:
 *
 * SEE ALSO:
 *   <xp_thr_start>
 */
int xp_thr_stop (xp_thr_t* thr);

/* 
 * FUNCTION: xp_thr_join
 *   Waits for termination of other threads
 *
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *
 * RETURNS:
 *   0 on success, -1 on failure
 *
 * SEE ALSO:
 *   <xp_thr_detach>
 */
int xp_thr_join (xp_thr_t* thr);

/* 
 * FUNCTION: xp_thr_detach
 *   Detaches a thread 
 *
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *
 * RETURNS:
 *   0 on success, -1 on failure
 *
 * SEE ALSO:
 *   <xp_thr_join>
 */
int xp_thr_detach (xp_thr_t* thr);

/* GROUP: Signal */

/* 
 * FUNCTION: xp_thr_kill
 */
int xp_thr_kill (xp_thr_t* thr, int sig);

/* 
 * FUNCTION: xp_thr_blocksig
 */
int xp_thr_blocksig (xp_thr_t* thr, int sig);

/* 
 * FUNCTION: xp_thr_unblocksig
 */
int xp_thr_unblocksig (xp_thr_t* thr, int sig);

/* 
 * FUNCTION: xp_thr_blockallsigs
 */
int xp_thr_blockallsigs (xp_thr_t* thr);

/* 
 * FUNCTION: xp_thr_unblockallsigs
 */
int xp_thr_unblockallsigs (xp_thr_t* thr);

/* GROUP: Miscellaneous */

/* 
 * FUNCTION: xp_thr_gethnd
 *   Returns the native handle
 */
xp_thrhnd_t xp_thr_gethnd (const xp_thr_t* thr);

/* 
 * FUNCTION: xp_thr_getretcode
 *   Returns the return code of a thread routine
 *
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *
 * RETURNS:
 *   Return code of the last thread routine that has been terminated
 *
 * DESCRIPTION:
 *   <xp_thr_getretcode> returns the return code of the last thread
 *   routine that has been terminated. If no thread routine has been 
 *   started and terminated, 0 is returned.
 */
int xp_thr_getretcode (const xp_thr_t* thr);

/* 
 * FUNCTION: xp_thr_state
 *   Returns the current state
 */
int xp_thr_getstate (const xp_thr_t* thr);

/*
 * FUNCTION: xp_thr_getuserdata
 *   Returns a user-provided data pointer
 *
 * PARAMETERS:
 *   thr - [in] pointer to a thread object
 *
 * RETURNS:
 *   Pointer to a user-provided data pointer
 *
 * DESCRIPTION:
 *   <xp_thr_getuserdata> returns a pointer to the data provided with 
 *   <xp_thr_open>. The data pointer is also accessible from within
 *   a thread routine by calling this function over the thread object passed.
 *   
 * SEE ALSO:
 *   <xp_thr_open>
 */
void* xp_thr_getuserdata (const xp_thr_t* thr);

/*
 * FUNCTION : xp_getcurthrhnd
 *   Returns the handle to the calling thread
 */
xp_thrhnd_t xp_getcurthrhnd (void);

#ifdef __cplusplus
}
#endif

#endif
